#ifndef SOCK5_CLIENTMGR_HPP
#define SOCK5_CLIENTMGR_HPP

#include "singleton.hpp"
#include "sock5client.hpp"
#include <memory>
#include <unordered_map>

namespace oraysock5 {
/**
 * @brief 连接db的客户端管理器
*/
class Sock5ClientMgr final : public Nocopy {
    friend class Singleton<Sock5ClientMgr>;

    Sock5ClientMgr() = default;

public:
    /**
    * @brief 类型名称
    */
    static constexpr const char* kClassname = "Sock5ClientMgr";
    ~Sock5ClientMgr() = default;

    /**
     * @brief 添加连接sock5的客户端连接
     * @param k sock5的客户端fd
     * @param v sock5的客户端连接
    */
    void add(int k, std::shared_ptr<Sock5Client> v);
    /**
     * @brief 移除连接sock5的客户端连接
     * @param k sock5的客户端fd
    */
    void remove(int k);
    /**
     * @brief 查找连接sock5的客户端连接
     * @param k sock5的客户端fd
     * @return 连接sock5的客户端连接,找不到返回nullptr
    */
    std::shared_ptr<Sock5Client> find(int k);

    /**
     * @brief 迭代所有管理的连接sock5的客户端连接
     * @param cb 迭代函数
    */
    void foreach_clis(std::function<void(int, std::shared_ptr<Sock5Client>)> cb) const;

    /**
     * @brief 获取sock5服务器监听地址
     * @return sock5服务器监听地址
    */
    const IPAddress& listen_addr() const { return listen_addr_; }
    /**
     * @brief 设置sock5服务器监听地址
     * @param addr sock5服务器监听地址 
    */
    void set_listen_addr(const IPAddress& addr) { listen_addr_ = addr; }

private:
    /**
     * @brief  sock5服务器监听地址 
    */
    IPAddress listen_addr_;
    /**
     * @brief 连接sock5的客户端fd与连接db的客户端映射的hash表
    */
    std::unordered_map<int, std::shared_ptr<Sock5Client>> clis_;
};
}

#endif
